﻿#include "stdafx.h"
#include "OpenGLFunctions.h"

void OpenGLInit(PictureBox^  picBox , HDC* m_hDC , HGLRC* m_hRC , HWND* m_hWnd)
{
	float rate_WH = (float)picBox->Size.Width / (float)picBox->Size.Height;
	
	//******************************************************************
	// Get Handle
	*m_hWnd = (HWND)picBox->Handle.ToInt32();
	*m_hDC = GetDC( *m_hWnd );
	//WGL::wglSwapBuffers((unsigned int)m_hDC);
	wglSwapBuffers(*m_hDC);

	// Set pixel format
	PIXELFORMATDESCRIPTOR pfd;
	//WGL::ZeroPixelDescriptor(pfd);
	pfd.nVersion   = 1; 
	pfd.dwFlags    = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
	pfd.iPixelType = (byte)(PFD_TYPE_RGBA);
	pfd.cColorBits = 32;
	pfd.cDepthBits = 32;
	pfd.iLayerType = (byte)(PFD_MAIN_PLANE);

	int nFormat = ChoosePixelFormat(*m_hDC, &pfd);
	SetPixelFormat(*m_hDC, nFormat, &pfd);

	// Create OpenGL Rendering Context
	*m_hRC = (wglCreateContext(*m_hDC));
	if (*m_hRC == 0) 
		MessageBox::Show("wglCreateContext Error");
	// Assign OpenGL Rendering Context
	if (wglMakeCurrent(*m_hDC, *m_hRC ) == false) 
		MessageBox::Show("wglMakeCurrent Error");


	glEnable(GL_TEXTURE_2D);						// 啟用紋理映射
	glShadeModel(GL_SMOOTH);						// 啟用陰影平滑
	glClearColor(0.8f, 0.8f, 0.8f, 0.5f);					// 黑色背景
	glClearDepth(1.0f);							// 設置深度緩存
	glEnable(GL_DEPTH_TEST);						// 啟用深度測試
	glDepthFunc(GL_LEQUAL);							// 所作深度測試的類型
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// 真正精細的透視修正
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glMatrixMode(GL_PROJECTION); 
	glLoadIdentity(); 
	gluPerspective( 45, rate_WH, 0.0001, 400.0); //透視投影

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	OpenGLSetLighting();

	//OpenGLLoadTextures("../Texture/Sky2/Top.bmp", &Texture[SkyTopTex]);
	//OpenGLLoadTextures("../Texture/Sky2/Bottom.bmp", &Texture[SkyBottomTex]);
	//OpenGLLoadTextures("../Texture/Sky2/Front.bmp", &Texture[SkyFrontTex]);
	//OpenGLLoadTextures("../Texture/Sky2/Back.bmp", &Texture[SkyBackTex]);
	//OpenGLLoadTextures("../Texture/Sky2/Left.bmp", &Texture[SkyLeftTex]);
	//OpenGLLoadTextures("../Texture/Sky2/Right.bmp", &Texture[SkyRightTex]);
	//OpenGLLoadTextures("../Texture/Hair.bmp", &Texture[HairTex]);
	//OpenGLLoadTextures("../Texture/Bball.bmp", &Texture[BballTex]);
	//OpenGLLoadTextures("../Texture/Obstacle.bmp", &Texture[ObstacleTex]);
	//OpenGLLoadTextures("../Texture/View.bmp", &Texture[ViewTex]);
	//LoadTGA(&TGATexture[0], "../Texture/Light.tga");

	//Model[ModelBasket].Materials[0].tex.Load("../Model/cloth.bmp");
	//Model[ModelBasket].Materials[1].tex.Load("../Model/EYJ.bmp");
	//Model[ModelField].Materials[0].tex.Load("../Model/Field2.bmp");
	//Model[ModelField].Materials[1].tex.Load("../Model/Goal.bmp");
	//Model[ModelField].Materials[2].tex.Load("../Model/Goal.bmp");
	//Model[ModelField].Materials[3].tex.Load("../Model/Goal.bmp");
	//Model[ModelField].Materials[4].tex.Load("../Model/Goal.bmp");
	//Model[ModelField].Materials[5].tex.Load("../Model/Goal.bmp");
	//Model[ModelField].Materials[6].tex.Load("../Model/Goal.bmp");
	////*********************************************************************

	//3D文字初始化
	//t3dInit();
}
void OpenGLShow(HDC m_hDC , HGLRC m_hRC , GLfloat camPos[3] ,  GLfloat camRot[3] , GLfloat camCoord[16])
{
	glPushMatrix();
		wglMakeCurrent( NULL, NULL );
		wglMakeCurrent(  m_hDC, m_hRC  );

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// 清除屏幕和深度緩存
		glLoadIdentity();										    // 重置當前的模型觀察矩陣

  		GLfloat camfocus[3];
		float R[3] = {0,0,0};
		float T[3] = {0,0,1};
		float original_focus[3] = {0,0,0};
		CoordTransPos(T, R, camCoord, original_focus, &camfocus[0]);

		//放大角度取餘數(象限)，避免資料流失，減少鏡頭顛倒瞬間時間
		float Quadrant = (float)((int)(System::Math::Abs(camRot[0]*180/M_PI)*1000)%360000)/90/1000;
		if (Quadrant >= 1.00 && Quadrant <= 3.00)
			gluLookAt(camPos[0],camPos[1],camPos[2],camfocus[0],camfocus[1],camfocus[2],0,-1,0);
		else
			gluLookAt(camPos[0],camPos[1],camPos[2],camfocus[0],camfocus[1],camfocus[2],0,1,0);


		OpenGLRender();

	glPopMatrix();
	SwapBuffers(m_hDC);
	glFlush();
}

void OpenGLRender()
{	
	OpenGLDrawAxis();
	float Shadow = 80;
	float sides[3] = {0.5, 0.1, 0.5};
	static float rot_angle = 0;
	float R[3] = {0};
	float rot_matrixX[16] = {0};
	float rot_matrixY[16] = {0};
	float rot_matrixZ[16] = {0};

	OpenGLSetLighting();
	OpenGLSetMaterialColor(0, 1, 0, 1, Shadow);
	OpenGLDrawBoxD(&BoardPos[0], &BoardRot[0], sides);

	rot_angle += 1;
	if(rot_angle == 360)
		rot_angle = 0;
	R[0] = rot_angle * System::Math::PI / 180;
	R[1] = -rot_angle * System::Math::PI / 180;
	//SetRotateMatrix(rot_angle, 0, &rot_matrixX[0]);
	//SetRotateMatrix(rot_angle, 1, &rot_matrixY[0]);
	//MetrixMultiplication(4, 4, 4, 4, &rot_matrixY[0], &rot_matrixX[0], &BoardRot[0]);
	CoordMultMatrix(BoardPos, R, WorldCoordMatrix, &BoardRot[0]);

	//float base_vector[3] = {0, 0, 1};
	//QuaternionRotateMetrix(rot_angle, &BoardRot[0], &base_vector[0], &BoardRot[0]);
}

void OpenGLSetLighting()
{
	float light_position[] = { -100, 50, -190 , 1};  //光源的位置
	float light_ambient[]  = { 1.0, 1.0, 1.0, 1.0}; 
	float light_diffuse[]  = { 1.0, 1.0, 1.0, 1.0}; 
	float light_specular[] = { 1.0, 1.0, 1.0, 1.0}; 

	glPushMatrix();
	glEnable(GL_LIGHTING);                                 //開燈 

	// 設定發光體的光源的特性 
	glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient);      //環境光(Ambient Light) 
	glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse);      //散射光(Diffuse Light) 
	glLightfv( GL_LIGHT0, GL_SPECULAR,light_specular);     //反射光(Specular Light) 
	glLightfv( GL_LIGHT0, GL_POSITION,light_position);     //光的座標 
	glEnable(GL_LIGHT0);    

	glPopMatrix(); 
}

void OpenGLDrawAxis()
{
	glBegin(GL_LINES);
		OpenGLSetMaterialColor(1, 0, 0, 1, 80);
		glVertex3f(0,0,0); 
		glVertex3f(10,0,0); 
	glEnd(); 
	glBegin(GL_LINES);
		OpenGLSetMaterialColor(0, 1, 0, 1, 80);
		glVertex3f(0,0,0); 
		glVertex3f(0,10,0);
	glEnd(); 
	glBegin(GL_LINES);
		OpenGLSetMaterialColor(0, 0, 1, 1, 80);
		glVertex3f(0,0,0); 
		glVertex3f(0,0,10);
	glEnd(); 
}

void OpenGLDrawBoxD (const float* pos, const float* R, const float* sides)
{
	int i;
	float fpos[3],fR[12],fsides[3];
	for (i=0; i<3; i++) fpos[i]=pos[i];
	for (i=0; i<12; i++) fR[i]=R[i];
	for (i=0; i<3; i++) fsides[i]=sides[i];

	glPushMatrix();
		OpenGLSetTransform (fpos,fR);
		OpenGLDrawBox (fsides);
	glPopMatrix();
}

void OpenGLDrawBox (const GLfloat sides[3])
{
	float lx = sides[0]*0.5f;
	float ly = sides[1]*0.5f;
	float lz = sides[2]*0.5f;

	//綁定紋理
	//glBindTexture(GL_TEXTURE_2D, Texture[HairTex]);
	
	//立方體

	glBegin(GL_QUADS);
	// 頂面
	OpenGLSetMaterialColor(1, 0, 0, 1, 80);
	glNormal3f (0,-1,0);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-lx, -ly,  lz);	// 紋理和四邊形的左下
	glTexCoord2f(1.0f, 0.0f); glVertex3f( lx, -ly,  lz);	// 紋理和四邊形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f( lx,  ly,  lz);	// 紋理和四邊形的右上
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-lx,  ly,  lz);	// 紋理和四邊形的左上
	// 底面
	OpenGLSetMaterialColor(0.5, 0, 0, 1, 80);
	glNormal3f (0,1,0);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-lx, -ly, -lz);	// 紋理和四邊形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-lx,  ly, -lz);	// 紋理和四邊形的右上
	glTexCoord2f(0.0f, 1.0f); glVertex3f( lx,  ly, -lz);	// 紋理和四邊形的左上
	glTexCoord2f(0.0f, 0.0f); glVertex3f( lx, -ly, -lz);	// 紋理和四邊形的左下
	// 左面
	OpenGLSetMaterialColor(0, 1, 0, 1, 80);
	glNormal3f (1,0,0);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-lx,  ly, -lz);	// 紋理和四邊形的左上
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-lx,  ly,  lz);	// 紋理和四邊形的左下
	glTexCoord2f(0.0f, 1.0f); glVertex3f( lx,  ly,  lz);	// 紋理和四邊形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f( lx,  ly, -lz);	// 紋理和四邊形的右上
	// 右面
	glNormal3f (-1,0,0);
	OpenGLSetMaterialColor(0, 0.5, 0, 1, 80);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-lx, -ly, -lz);	// 紋理和四邊形的右上
	glTexCoord2f(1.0f, 0.0f); glVertex3f( lx, -ly, -lz);	// 紋理和四邊形的左上
	glTexCoord2f(0.0f, 0.0f); glVertex3f( lx, -ly,  lz);	// 紋理和四邊形的左下
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-lx, -ly,  lz);	// 紋理和四邊形的右下
	// 前面
	glNormal3f (0,1,1);
	OpenGLSetMaterialColor(0, 0, 1, 1, 80);
	glTexCoord2f(1.0f, 0.0f); glVertex3f( lx, -ly, -lz);	// 紋理和四邊形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f( lx,  ly, -lz);	// 紋理和四邊形的右上
	glTexCoord2f(0.0f, 1.0f); glVertex3f( lx,  ly,  lz);	// 紋理和四邊形的左上
	glTexCoord2f(0.0f, 0.0f); glVertex3f( lx, -ly,  lz);	// 紋理和四邊形的左下
	// 後面
	OpenGLSetMaterialColor(0, 0, 0.5, 1, 80);
	glNormal3f (0,-1,1);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-lx, -ly, -lz);	// 紋理和四邊形的左下
	glTexCoord2f(1.0f, 0.0f); glVertex3f(-lx, -ly,  lz);	// 紋理和四邊形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f(-lx,  ly,  lz);	// 紋理和四邊形的右上
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-lx,  ly, -lz);	// 紋理和四邊形的左上
	glEnd();
}

void OpenGLSetMaterialColor(GLfloat R, GLfloat G, GLfloat B, GLfloat Alpha, GLfloat Shadow)
{
	Shadow = Shadow < 1 ? 1 : Shadow;
	Shadow = Shadow > 100 ? 100 : Shadow;

	//Shadow 1~100之間，100陰影最明顯
	GLfloat mat_ambient[] = {R - (R*(Shadow/100.0)), G - (G*(Shadow/100.0)), B-(B*(Shadow/100.0)), Alpha};	//環境光(Ambient Light) 
	GLfloat mat_diffuse[] = {R - (R*(Shadow/200.0)), G - (G*(Shadow/200.0)), B - (B*(Shadow/200.0)), Alpha};	//散射光(Diffuse Light) 
	GLfloat mat_specular[] =  {R, G, B, Alpha};	//反射光(Specular Light) 
	GLfloat mat_emission[] = {R - (R*(Shadow/200.0)), G - (G*(Shadow/200.0)), B - (B*(Shadow/200.0)), Alpha};
	GLfloat shininess[] = {100};

	glMaterialfv(GL_FRONT,GL_AMBIENT, mat_ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
	glMaterialfv(GL_FRONT,GL_SHININESS, shininess);
}

void OpenGLSetTransform (const GLfloat pos[3], const GLfloat R[12])
{
	GLfloat matrix[16];
	matrix[0]=R[0];
	matrix[1]=R[4];
	matrix[2]=R[8];
	matrix[3]=0;
	matrix[4]=R[1];
	matrix[5]=R[5];
	matrix[6]=R[9];
	matrix[7]=0;
	matrix[8]=R[2];
	matrix[9]=R[6];
	matrix[10]=R[10];
	matrix[11]=0;
	matrix[12]=pos[0];
	matrix[13]=pos[1];
	matrix[14]=pos[2];
	matrix[15]=1;
	
	glMultMatrixf (matrix);
}

void OpenGLCrossProduct3(GLfloat res[3], const GLfloat a[3], const GLfloat b[3])
{
	float res_0 = a[1]*b[2] - a[2]*b[1];
	float res_1 = a[2]*b[0] - a[0]*b[2];
	float res_2 = a[0]*b[1] - a[1]*b[0];
	// Only assign after all the calculations are over to avoid incurring memory aliasing
	res[0] = res_0;
	res[1] = res_1;
	res[2] = res_2;
}
void OpenGLNormalizeVector3 (GLfloat v[3])
{
	float len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
	if (len <= 0.0f) {
		v[0] = 1;
		v[1] = 0;
		v[2] = 0;
	}
	else {
		len = 1.0f / (float)sqrt(len);
		v[0] *= len;
		v[1] *= len;
		v[2] *= len;
	}
}